package service

import (
	"github.com/ahmetb/go-linq/v3"
	psnet "github.com/shirou/gopsutil/v3/net"
	"github.com/sirupsen/logrus"
	"miao-wails/backed/app/dao"
	"miao-wails/backed/lib/utils"
	"miao-wails/backed/structs/idp"
	"miao-wails/backed/structs/tables"
	"net"
	"strings"
)

var IdpServ = new(idpService)

type idpService struct {
}

// UploadLogs 上传日志
func (s idpService) UploadLogs() (err error) {
	var li []tables.CollectInfo
	li, err = dao.IdpDao.FindLogsForAck2()
	if err != nil {
		return
	}
	// todo 将数据发送到kafka中，发送完毕后修改本地日志的状态，避免反复发送
	logrus.Debug(li)
	return
}

func (s idpService) GetCollectLogs() (li []tables.CollectInfo, err error) {
	li1, err := dao.IdpDao.FindLogsForAck2()
	if err != nil {
		return
	}
	t0 := utils.GetToday0()
	t24 := utils.GetToday24()
	li2, err := dao.IdpDao.FindLogsForTime(t0.Unix()-utils.Day, t24.Unix())
	if err != nil {
		return
	}
	li1 = append(li1, li2...)
	linq.From(li1).DistinctBy(func(i interface{}) interface{} {
		return i.(tables.CollectInfo).Id
	}).OrderBy(func(it interface{}) interface{} {
		return it.(tables.CollectInfo).CreateAt
	}).ToSlice(&li)
	return
}

// GetPcBaseInfo 获取基础信息
func (s idpService) GetPcBaseInfo() (out idp.PcBaseInfo, err error) {
	var (
		sys        idp.Sys
		cpu        idp.Cpu
		mem        []idp.Memory
		disk       []idp.LogicDisk
		netw       idp.Network
		diskSerial []string
	)
	if sys, err = s.getSysInfo(); err != nil {
		return
	}
	if cpu, err = s.getCpu(); err != nil {
		return
	}
	if mem, err = s.getMemory(); err != nil {
		return
	}
	if disk, err = s.getDisk(); err != nil {
		return
	}
	if netw, err = s.getNetwork(); err != nil {
		return
	}
	if diskSerial, err = s.getDiskSerialList(); err != nil {
		return
	}
	out = idp.PcBaseInfo{
		Sys:        sys,
		Cpu:        cpu,
		Memory:     mem,
		Disk:       disk,
		Network:    netw,
		DiskSerial: diskSerial,
	}
	return
}

func (s idpService) GetConfig() (out idp.Config, err error) {
	// todo 网络请求配置信息

	out = idp.Config{
		InnerNet:    "111",
		InterNet:    "111",
		NetLv:       "inter",
		UniqueType:  "disk+bios",
		UniqueValue: "abc",
		DeviceId:    "1234",
		HttpEcho:    60,
		OpenTcp:     false,
	}
	return
}

func (s idpService) getIpMAC() (ip, mac string, err error) {
	var psn psnet.InterfaceStatList
	if ip, err = s.getOutBoundIp(); err != nil {
		return
	}
	if psn, err = psnet.Interfaces(); err != nil {
		return
	}
	for _, item := range psn {
		for _, ad := range item.Addrs {
			ipv4 := s.formatIpv4(ad.Addr)
			if ipv4 == ip {
				mac = strings.ReplaceAll(item.HardwareAddr, ":", "-")
				return ip, mac, nil
			}
		}
	}
	return
}

func (s idpService) formatIpv4(str string) string {
	if strings.LastIndex(str, "/") > 0 {
		str = str[:strings.LastIndex(str, "/")]
	}
	arr := strings.Split(str, ".")
	if len(arr) == 4 {
		return utils.ArrStringToStr2(arr, ".")
	}
	return ""
}

func (s idpService) getOutBoundIp() (ip string, err error) {
	var conn net.Conn
	conn, err = net.Dial("udp", "8.8.8.8:80")
	if err != nil {
		return
	}
	localAdd := conn.LocalAddr()
	ip = strings.Split(localAdd.String(), ":")[0]
	return
}
